var uuid = require('node-uuid');
var promise = require('bluebird');
var logger = require('winston');
var math = require('mathjs');
var moment = require('moment');
var fs = promise.promisifyAll(require('fs-extra'));
var winston = require('winston');
var cons = require('consolidate');
var process = promise.promisifyAll(require('child_process'));

module.exports = {
    /**
     * Ensures that a directory is empty. Deletes directory contents if the
     * directory is not empty. If the directory does not exist, it is created.
     * The directory itself is not deleted.
     */
    cleanDir: (dir, callback) => {
        return fs.emptyDirAsync(dir, callback);
    },
    /**
     * Removes a file or directory. The directory can have contents. Like rm
     * -rf.
     */
    deleteDir: (dir, callback)=> {
        return fs.removeAsync(dir, callback);
    },
    copy: (src, dest, options, callback) => {
        return fs.copyAsync(src, dest, options, callback);
    },
    createFile: (dir, callback) => {
        return fs.ensureFileAsync(dir, callback);
    },
    ensureFile: (dir, callback)=> {
        return fs.ensureFileAsync(dir, callback);
    },
    createDir: (dir, callback)=> {
        return fs.ensureDirAsync(dir, callback);
    },
    ensureDir: (dir, callback) => {
        return fs.ensureDirAsync(dir, callback);
    },
    writeJson: (file, object, options, callback)=> {
        return fs.writeJsonAsync(file, object, options, callback);
    },
    readJson: (file, options, callback) => {
        return fs.readJsonAsync(file, options, callback);
    },
    generateUUID: (callback)=> {
        return uuid.v4();
    },
    openSystemDefaultBrowser: (url, options, callback) => {
        return process.execAsync(`open '${url}' `, options, callback);
    },
    execCommand: (command, options, callback) => {
        return process.execAsync(command, options, callback);
    },
    formatFloat: (s, n, callback)=> {
        n = n > 0 && n <= 20 ? n : 2;
        var s = parseFloat((s + "").replace(/[^\d\.-]/g, "")).toFixed(n) + "";
        return promise.resolve(s).asCallback(callback);
    },
    formatFloat: (s, callback) => {
        var s = parseFloat((s + "").replace(/[^\d\.-]/g, "")).toFixed(2) + "";
        return promise.resolve(s).asCallback(callback);
    },
    generateOrderNo: ()=> {
        return math.randomInt(1000, 9999) + "" + moment().valueOf() + "";
    },
    parseJson: (json)=> {
        return JSON.parse(json);
    },
    toJson: (obj)=> {
        return JSON.stringify(obj);
    },
    renderWithMustache: (tmpl, source, callback)=> {
        return cons.mustache(tmpl, source, callback);
    },
    writeFile: (file, data, callback)=> {
        return fs.writeFileAsync(file, data, callback);
    },
    isEmailValid: (emailAddress) => {
        var expToken = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
        return expToken.test(emailAddress);
    },
    getLogger: () => {
        return new (winston.Logger)(
            {
                transports: [new (winston.transports.Console)(
                    {
                        timestamp: () => {
                            return moment().format();
                        },
                        formatter: (options)=> {
                            // Return string will be passed to logger.
                            return options.timestamp()
                                + ' '
                                + options.level.toUpperCase()
                                + ' '
                                + (undefined !== options.message ? options.message
                                    : '')
                                + (options.meta
                                && Object
                                    .keys(options.meta).length ? '\n\t'
                                + JSON
                                    .stringify(options.meta)
                                    : '');
                        }
                    })]
            });
    }
};
